home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS03.ADF / Xref / xref.c < prev    next >
C/C++ Source or Header  |  1986-04-02  |  13KB  |  404 lines

  1. /*************************************************************************
  2.  
  3. NAME
  4.  
  5.    xref -- make list of all words and a file and the line numbers of
  6.            their occurrences, excluding C keywords, words within
  7.            quotation marks, and words within C comment markers, unless
  8.            overridden.
  9.  
  10. USAGE
  11.  
  12.    xref <input >output  -k -q -c
  13.  
  14.       where  -k causes inclusion of C keywords
  15.              -q causes inclusion of words within quotes (")
  16.              -c causes inclusion of words within C comment markers
  17.  
  18. DESCRIPTION
  19.  
  20.    A "word" is a string of letters and digits beginning with a letter.
  21.  
  22. AUTHOR    Philip T. Ansteth
  23. DATE      December 6, 1985
  24. CLIENT    ANSTETH RESEARCH
  25.           P.O. Box 35882
  26.           Tulsa, Ok.
  27.  
  28.  
  29. CALLED FUNCTIONS
  30.  
  31.    getmem       -- gets memory from system pool
  32.  
  33.  
  34.  
  35. LINKAGE INFORMATION
  36.  
  37.      The link command from the CLI is
  38.  
  39.           alink with xref.lnk
  40.  
  41.      The file alink.lnk must contain:
  42.  
  43.           FROM     Lstartup.obj,   *
  44.                    df1:cs/xref.o, *
  45.                    df1:cs/getword.o, *
  46.                    df1:cs/getch.o, *
  47.                    df1:cs/type.o, *
  48.                    df1:cs/strsave.o
  49.           TO       df1:cs/xref
  50.           LIBRARY  lc.lib, df1:lib/amiga.lib
  51.           MAP      :nil 
  52.  
  53.  
  54.  
  55.  
  56. **************************************************************************/
  57.  
  58. #include <stdio.h>
  59.  
  60. /* define a template of a struct of type tnode */
  61. /* This type will contain info. about each word encountered */
  62. struct tnode {
  63.    char *word;          /* pointer to text string */
  64.    int count;           /* number of occurrences */
  65.    int linenum;         /* first line number */
  66.    struct tnode *left;  /* pointer to left child */
  67.    struct tnode *right; /* pointer to right child */
  68.    struct lnode *next;  /* pointer to line number list */
  69. };
  70.  
  71. /* define a template of a struct of type lnode */
  72. /* This type will contain line numbers */ 
  73. struct lnode {
  74.    int linenum;         /* line number */
  75.    struct lnode *next;  /* pointer to descendent */
  76. };
  77.  
  78. /* global values for determining when to do line feed on line number list*/
  79. #define  MAXPER   10
  80. int lnktrl;
  81.  
  82. char *keytab[] = {
  83.    "auto",
  84.    "break",
  85.    "case",
  86.    "char",
  87.    "continue",
  88.    "default",
  89.    "do",
  90.    "double",
  91.    "else",
  92.    "entry",
  93.    "extern",
  94.    "float",
  95.    "for",
  96.    "goto",
  97.    "if",
  98.    "int",
  99.    "long",
  100.    "register",
  101.    "return",
  102.    "short",
  103.    "sizeof",
  104.    "static",
  105.    "struct",
  106.    "switch",
  107.    "typedef",
  108.    "union",
  109.    "unsigned",
  110.    "while"
  111. };
  112.  
  113. #define NKEYS  (sizeof(keytab) / sizeof(keytab[0]))
  114.  
  115. #define  MAXWORD   20   /* max no. of chars in a word */
  116. #define  LETTER    'a'  /* code indicating an alpha character, a-z,A-Z */
  117. #define  DIGIT     '0'  /* code indicating a digit, 0-9 */
  118.  
  119. int incomments=0;  /*global flag indicating whether within C comment markers */
  120. int inquotes=0;    /*global flag indicating whether within quotation marks */
  121.  
  122. /* mainline */
  123. main(argc,argv)
  124. int argc;
  125. char *argv[];
  126. {
  127.    struct tnode *root, *tree();    /* root is a pointer to a structure
  128.                                       of type tnode; tree is a function
  129.                                       returning a pointer to a structure
  130.                                       of type tnode */
  131.    char word[MAXWORD];             /* character array for storing word */
  132.    int t;                          /* receives type code from getwordl */
  133.    int lnumber=1;                  /* line number counter */
  134.    char *s;                        /* command line argument receiver */
  135.    int kwords=0,quotes=0,comments=0;     /* flags for command line options */
  136.    int useflag=0;               /* flag stating whether this word is used */
  137.  
  138.  
  139.    while (--argc > 0 && (*++argv)[0] == '-') /* scan for optional flags */
  140.       for (s = argv[0]+1; *s != '\0' ; s++)  /* scan for string terminator.*/
  141.          switch(*s) {                        /* s is initialized with*/
  142.          case 'k':                           /* pointer to 1st character*/
  143.             kwords = 1;                      /*   after that pointed to by*/
  144.             break;                           /*   argv */
  145.          case 'q':
  146.             quotes = 1;
  147.             break;
  148.          case 'c':
  149.             comments = 1;
  150.             break;
  151.          default:
  152.             printf("xref: illegal option %c\n", *s);
  153.             argc = 1;        /* make sure error message will be printed */
  154.             break;
  155.          }
  156.    if (argc != 0) {/* expect argc to equal 0 at end of previous while
  157.                      and argv now is address containing pointer to
  158.                      last argument */
  159.       printf("Usage: xref <input >output  -k -q -c\n");
  160.       exit(1);
  161.    }
  162.  
  163.    root=NULL;                                  /* first time root is NULL */
  164.    /* read each word in file and install it somewhere in the tree */
  165.    while ((t = getwordl(word,MAXWORD,&lnumber)) != EOF)
  166.       if (t == LETTER) {
  167.          useflag = 1;
  168.          /* are we excluding C keywords? */
  169.          if (kwords == 0) 
  170.              if (binary(word,keytab,NKEYS) >= 0)
  171.                 useflag = 0;
  172.          /* are we excluding words within quotes? */
  173.          if (quotes == 0)
  174.              if (inquotes == 1)
  175.                 useflag = 0;
  176.          /* are we excluding words within comment markers? */
  177.          if (comments == 0)
  178.              if (incomments == 1)
  179.                 useflag = 0;
  180.          if (useflag == 1)
  181.             root = tree(root,word,lnumber);
  182.       }
  183.    if(incomments == 1)
  184.       printf("xref:  WARNING--unbalanced C comment markers\n");
  185.    if(inquotes == 1)
  186.       printf("xref:  WARNING--unbalanced quotation marks\n");
  187.  
  188.    treeprint(root);                             /* print out the tree */
  189. }
  190. /*************************************************************************/
  191. /* function to install word in tree */
  192. struct tnode *tree(p,w,lnumber)   /* returns pointer to a tnode struct */
  193. struct tnode *p;        /* UPDATE pointer to tnode structure */
  194. char *w;                /* INPUT  pointer to a char string containing word */
  195. int lnumber;            /* INPUT  linenumber where word occurs */
  196. {
  197.    struct tnode *talloc();   /* talloc is a function returning a pointer
  198.                                 to a structure of type tnode */
  199.    char *strsave();          /* strsave is a function returning a point
  200.                                 to a character string */
  201.    int cond;                 /* holds result of strcmp */
  202.    struct lnode *list();     /* function returning pointer to lnode struct*/
  203.  
  204.  
  205.    if (p == NULL) {                 /* has a new word arrived? */
  206.       p = talloc();                 /* allocate space &
  207.                                        return pointer for a new node */
  208.       p->word = strsave(w);         /* fill in word */
  209.       p->linenum = lnumber;         /* fill in first line number */
  210.       p->count = 1;                 /* initialize counter */
  211.       p->left = p->right = p->next = NULL;     /* set pointers to NULL */
  212.    }
  213.  
  214.    else if ((cond = strcmp(w, p->word)) == 0) {  /* is it a repeated word? */
  215.       p->count++;                                /* increment counter */
  216.       p->next=list(p->next,lnumber);           /* install line no. at end */
  217.    }
  218.  
  219.    else if (cond < 0)      /* are there more to look at in  left subtree? */
  220.       p->left = tree(p->left, w,lnumber); /* install it somewhere to the left */
  221.  
  222.    else                    /* greater into right subtree */
  223.       p->right = tree(p->right,w,lnumber);
  224.    return(p);              /* return pointer */
  225. }
  226.  
  227. /*************************************************************************/
  228. /* function to install line number at end of list */
  229. struct lnode *list(lp,lnumber)
  230. struct lnode *lp;           /* UPDATE:  pointer to lnode struct */
  231. int lnumber;                /* INPUTE:  line number where word occurred */
  232. {
  233.    struct lnode *lalloc();  /* function returning pointer to lnode struct */
  234.  
  235.  
  236.    if(lp == NULL) {            /* is this the end of the list? */
  237.       lp = lalloc();           /* get pointer for next node */
  238.       lp->linenum = lnumber;   /* install line number there */
  239.       lp->next = NULL;         /* fill in NULL to end list there */
  240.    }
  241.    else
  242.       lp->next=list(lp->next,lnumber);   /* go on to next node */
  243.  
  244.    return(lp);               /* return pointer for installation by caller */
  245.  
  246. }
  247.  
  248.  
  249. /*************************************************************************/
  250. /* function to print tree recursively,
  251.          using "left tree" order  */
  252. treeprint(p)
  253. struct tnode *p;        /* INPUT:  pointer to tnode struct */
  254. {
  255.    static int ifirst=1;      /* first time flag */
  256.  
  257.  
  258.  
  259.    if(ifirst == 1) {         /* print headers on first time through */
  260.       ifirst = 0;
  261.       printf("\n");
  262.       printf("Cross Reference Utility\n\n");
  263.       printf("Count   Word                   Lines where occurring\n\n");
  264.    }
  265.  
  266.    if(p != NULL) {
  267.       treeprint(p->left);                    /* do left branch first */
  268.       printf("%5d   %-20.20s   %4d",         /* print current data */
  269.          p->count,p->word,p->linenum);
  270.       lnktrl=1;                              /* set line no. counter to 1 */
  271.       listprint(p->next);                    /* print line occurrences */
  272.       treeprint(p->right);                   /* now do right branch */
  273.    }
  274. }
  275.  
  276. /*************************************************************************/
  277. /* function to print out line numbers of word occurrences */
  278. listprint(lp)
  279. struct lnode *lp;    /* INPUT:  pointer to lnode struct */
  280. {
  281.  
  282.     if(lp != NULL)  {
  283.       if(lnktrl < MAXPER) {
  284.          printf(" %d",lp->linenum);
  285.          lnktrl++;
  286.       }
  287.       else  {
  288.          printf("\n                                   %d",lp->linenum);
  289.          lnktrl=1;
  290.       }
  291.       listprint(lp->next);
  292.     }
  293.     else
  294.       printf("\n");
  295. }
  296.       
  297. /*************************************************************************/
  298. /* function to allocate memory for tnode struct */
  299. struct tnode *talloc()      /* get memory for structure and return
  300.                                pointer of the correct type */
  301. {
  302.    char *getmem();           /* getmem is a subroutine returning
  303.                                a pointer to a character */
  304.  
  305.  
  306.    return(
  307.       (struct tnode *)      /* coerce getmem to a pointer t  a tnode struct */
  308.       getmem(sizeof(struct tnode)) /* get memory for a tnode structure */
  309.    );
  310. }
  311.  
  312. /*************************************************************************/
  313. /* function to allocate memor∙ for lnode struct */
  314. struct lnode *lalloc()
  315. {
  316.    char *getmem();
  317.  
  318.  
  319.    return( (struct lnode *) getmem(sizeof(struct lnode)));
  320. }
  321.  
  322. /*************************************************************************/
  323. /* function to get next word from input */
  324. getwordl(w,lim,plnumber)     /* get next word from input */
  325. char *w;                 /* OUTPUT: pointer to word found */
  326. int lim;                 /* INPUT:  maximum word length */
  327. int *plnumber;           /* UPDATE: line number where word found */
  328.                          /* returns LETTER when word found */
  329.                          /* otherwise returns most recent non-alpha char */
  330. {
  331.    int c,t;    /* receive output of getch and type functions */
  332.  
  333.  
  334.  
  335.    if ( (c = getch()) == '"')
  336.         inquotes = !inquotes;
  337.    ungetch(c);
  338.  
  339.    if (incomments == 0)  {
  340.         c = getch();
  341.         t = getch();
  342.         if (c  == '/' && t == '*')
  343.            incomments = 1;
  344.         ungetch(t);
  345.         ungetch(c);
  346.     }
  347.     else if (incomments == 1) {
  348.         c = getch();
  349.         t = getch();
  350.         if (c  == '*' && t == '/')
  351.            incomments = 0;
  352.         ungetch(t);
  353.         ungetch(c);
  354.      }
  355.  
  356.  
  357.    if(type(c = *w++ = getch()) != LETTER) { /* is first character non-alpha? */
  358.       *w = '\0';  /* second character of w is string terminator */
  359.  
  360.       if( c == '\n')
  361.           *plnumber += 1;
  362.       return(c);  /* return character in c too */
  363.    }
  364.    while (--lim > 0) {     /* check subsequent characters up to lim */
  365.       t = type(c = *w++ = getch());  /* put alpha or num. in w and t */
  366.       if (t != LETTER && t != DIGIT)  {
  367.          ungetch(c);
  368.          break;
  369.       }
  370.    }
  371.    *(w-1) = '\0';  /* reached end, so back up and put in string delimiter */
  372.  
  373.  
  374.    return(LETTER);
  375.  
  376. }
  377.  
  378.  
  379. /*************************************************************************/
  380. binary(word,tab,n) /* find word in tab[0]. . .tab[n-1] */
  381. char *word;
  382. char *tab[];      /* tab is a table of pointers */
  383. int n;
  384. {
  385.    int cond;
  386.    int low;
  387.    int high;
  388.    int mid;
  389.  
  390.    low = 0;
  391.    high = n-1;
  392.  
  393.    while(low <= high) {
  394.       mid =  (high+low) / 2;
  395.       if ((cond=strcmp(word,tab[mid])) < 0)
  396.          high = mid-1;
  397.       else if (cond > 0)
  398.          low = mid+1;
  399.       else
  400.          return(mid);
  401.    }
  402.    return(-1);
  403. }
  404.